package web_api

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"gitee.com/rw555/fdsmastergo/internal/bluetooth"
	"gitee.com/rw555/fdsmastergo/internal/monitor"
	"gitee.com/rw555/fdsmastergo/pkg/config"
	"gitee.com/rw555/fdsmastergo/pkg/device"
	"gitee.com/rw555/fdsmastergo/pkg/logger"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// Handler Web API处理器
type Handler struct {
	Monitor      *monitor.Monitor
	Device       device.Device
	ConfigClient *config.Client
	SystemConfig map[string]interface{}
	AudioManager *AudioManager // 音频管理器
}

// NewHandler 创建新的Web API处理器
func NewHandler(m *monitor.Monitor, d device.Device) *Handler {
	// 获取程序运行路径
	execPath, err := os.Executable()
	if err != nil {
		logger.SystemError("获取程序运行路径失败", zap.Error(err))
		return nil
	}
	// 获取程序所在目录
	baseDir := filepath.Dir(execPath)
	logger.SystemInfo("程序运行目录", zap.String("baseDir", baseDir))

	// 创建音频管理器，使用程序目录
	configClient := config.NewClient("http://127.0.0.1:8082")
	systemConfig, err := configClient.LoadConfigs()
	if err != nil {
		logger.SystemError("加载配置失败", zap.Error(err))
		return nil
	}

	audioManager, err := NewAudioManager(systemConfig, baseDir)
	if err != nil {
		logger.SystemError("创建音频管理器失败", zap.Error(err))
		return nil
	}

	return &Handler{
		Monitor:      m,
		Device:       d,
		ConfigClient: configClient,
		SystemConfig: systemConfig,
		AudioManager: audioManager,
	}
}

// HandleLogin 处理登录请求
func (h *Handler) HandleLogin(c *gin.Context) {
	var login struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}
	if err := c.BindJSON(&login); err != nil {
		logger.SystemWarn("登录请求数据无效", zap.Error(err))
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的请求数据"})
		return
	}

	logger.SystemInfo("用户尝试登录", zap.String("username", login.Username))

	// 验证用户名和密码
	var userRole string
	if login.Username == "admin" && login.Password == "admin" {
		userRole = "admin"
		logger.SystemInfo("管理员登录成功", zap.String("username", login.Username))
	} else if login.Username == "user" && login.Password == "user" {
		userRole = "user"
		logger.SystemInfo("普通用户登录成功", zap.String("username", login.Username))
	} else {
		logger.SystemWarn("登录失败，用户名或密码错误", zap.String("username", login.Username))
		c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
		return
	}

	// 设置cookie，确保路径为根路径，这样所有页面都能访问
	c.SetCookie("user_role", userRole, 3600, "/", "", false, false) // 注意：将HttpOnly设置为false，允许JavaScript访问
	c.SetCookie("username", login.Username, 3600, "/", "", false, false)

	logger.SystemInfo("设置Cookie成功",
		zap.String("user_role", userRole),
		zap.String("username", login.Username))

	c.JSON(http.StatusOK, gin.H{
		"message":  "登录成功",
		"role":     userRole,
		"username": login.Username,
	})
}

// HandleLogout 处理登出请求
func (h *Handler) HandleLogout(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"message": "退出成功"})
}

// HandleGetConfig 处理获取配置请求
func (h *Handler) HandleGetConfig(c *gin.Context) {
	// 使用配置客户端获取所有配置
	allConfig, err := h.ConfigClient.LoadConfigs()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("获取配置失败: %v", err)})
		return
	}

	c.JSON(http.StatusOK, allConfig)
}

// HandleUpdateConfig 处理更新配置请求
func (h *Handler) HandleUpdateConfig(c *gin.Context) {
	var config struct {
		Key   string `json:"key"`
		Value string `json:"value"`
	}
	if err := c.BindJSON(&config); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的请求数据"})
		return
	}
	// 验证参数
	if config.Key == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "键名不能为空"})
		return
	}

	// 使用配置客户端更新配置
	if err := h.ConfigClient.UpdateConfig(config.Key, config.Value); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"message": fmt.Sprintf("更新配置失败: %v", err)})
		return
	}

	// 根据配置键前缀判断是否需要通知相应的服务
	if h.isMonitorConfig(config.Key) {
		// 通知 monitor_server 刷新配置
		logger.SystemInfo("检测到monitor配置更新", zap.String("configKey", config.Key))

		// 发送通知到云服务
		monitorServerUrl := "http://localhost:8081/internal/refresh-config"
		notifyResp, err := http.Post(monitorServerUrl, "application/json", bytes.NewBuffer([]byte("{}")))
		if err != nil {
			logger.Warn("通知监控服务刷新配置失败", zap.Error(err), zap.String("configKey", config.Key))
			// 即使通知失败，也返回更新成功，因为配置已经更新到配置服务
			c.JSON(http.StatusOK, gin.H{"message": "配置已更新，但通知监控服务刷新失败"})
			return
		}

		// 检查响应状态
		if notifyResp.StatusCode != http.StatusOK {
			logger.Warn("云服务刷新配置返回非成功状态码",
				zap.Int("statusCode", notifyResp.StatusCode),
				zap.String("configKey", config.Key))
			c.JSON(http.StatusOK, gin.H{"message": "配置已更新，但云服务刷新可能失败"})
			return
		}
		defer notifyResp.Body.Close()

		logger.SystemInfo("已通知云服务刷新配置", zap.String("configKey", config.Key))
	} else if h.isMQTTConfig(config.Key) {
		// 通知 MQTT 服务刷新配置
		logger.SystemInfo("检测到MQTT配置更新", zap.String("configKey", config.Key))

		// 发送通知到云服务
		cloudServerUrl := "http://localhost:8084/api/v1/refresh-config"
		notifyResp, err := http.Post(cloudServerUrl, "application/json", bytes.NewBuffer([]byte("{}")))
		if err != nil {
			logger.Warn("通知云服务刷新配置失败", zap.Error(err), zap.String("configKey", config.Key))
			// 即使通知失败，也返回更新成功，因为配置已经更新到配置服务
			c.JSON(http.StatusOK, gin.H{"message": "配置已更新，但通知云服务刷新失败"})
			return
		}
		defer notifyResp.Body.Close()

		// 检查响应状态
		if notifyResp.StatusCode != http.StatusOK {
			logger.Warn("云服务刷新配置返回非成功状态码",
				zap.Int("statusCode", notifyResp.StatusCode),
				zap.String("configKey", config.Key))
			c.JSON(http.StatusOK, gin.H{"message": "配置已更新，但云服务刷新可能失败"})
			return
		}

		logger.SystemInfo("已通知云服务刷新配置", zap.String("configKey", config.Key))
	} else if h.isBluetoothConfig(config.Key) {
		// 通知蓝牙服务刷新配置
		logger.SystemInfo("检测到蓝牙配置更新", zap.String("configKey", config.Key))

		// 发送通知到蓝牙服务
		bluetoothServerUrl := "http://localhost:8083/api/v1/refresh-config"
		notifyResp, err := http.Post(bluetoothServerUrl, "application/json", bytes.NewBuffer([]byte("{}")))
		if err != nil {
			logger.Warn("通知蓝牙服务刷新配置失败", zap.Error(err), zap.String("configKey", config.Key))
			// 即使通知失败，也返回更新成功，因为配置已经更新到配置服务
			c.JSON(http.StatusOK, gin.H{"message": "配置已更新，但通知蓝牙服务刷新失败"})
			return
		}

		// 检查响应状态
		if notifyResp.StatusCode != http.StatusOK {
			logger.Warn("蓝牙服务刷新配置返回非成功状态码",
				zap.Int("statusCode", notifyResp.StatusCode),
				zap.String("configKey", config.Key))
			c.JSON(http.StatusOK, gin.H{"message": "配置已更新，但蓝牙服务刷新可能失败"})
			return
		}

		logger.SystemInfo("已通知蓝牙服务刷新配置", zap.String("configKey", config.Key))
	} else {
		logger.SystemInfo("检测到其他配置更新", zap.String("configKey", config.Key))
	}

	c.JSON(http.StatusOK, gin.H{"message": "更新成功"})
}

// HandleGetStatus 处理获取状态请求
func (h *Handler) HandleGetStatus(c *gin.Context) {
	// 从 monitor_server 获取状态
	resp, err := http.Get("http://127.0.0.1:8081/api/status")
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取状态失败"})
		return
	}
	defer resp.Body.Close()

	var status struct {
		Temperature           int      `json:"temperature"`
		Power                 int      `json:"power"`
		Modes                 []string `json:"modes"`
		HeatingStatus         bool     `json:"heating_status"`
		CoolingStatus         bool     `json:"cooling_status"`
		CurrentWorkingMinutes int      `json:"current_working_minutes"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&status); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "解析状态失败"})
		return
	}

	// 将布尔值转换为更友好的文本
	heatingStatusText := "关闭"
	if status.HeatingStatus {
		heatingStatusText = "开启"
	}

	coolingStatusText := "关闭"
	if status.CoolingStatus {
		coolingStatusText = "开启"
	}

	c.JSON(http.StatusOK, gin.H{
		"temperature":             status.Temperature,
		"power":                   status.Power,
		"modes":                   status.Modes,
		"heating_status":          heatingStatusText,
		"cooling_status":          coolingStatusText,
		"current_working_minutes": status.CurrentWorkingMinutes,
	})
}

// HandleSetMode 处理设置模式请求
func (h *Handler) HandleSetMode(c *gin.Context) {
	var req struct {
		Mode   string `json:"mode"`
		Option string `json:"option"`
	}
	if err := c.BindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的请求数据"})
		return
	}

	// 转发到 monitor_server
	resp, err := http.Post(
		"http://127.0.0.1:8081/api/mode",
		"application/json",
		bytes.NewReader([]byte(fmt.Sprintf(`{"mode":"%s","option":"%s"}`, req.Mode, req.Option))),
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "设置模式失败"})
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		c.JSON(resp.StatusCode, gin.H{"error": "设置模式失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "设置模式成功"})
}

// GetCurrentTemp 获取当前温度
func (h *Handler) GetCurrentTemp(c *gin.Context) {
	c.JSON(200, gin.H{
		"current_temp": h.Device.GetTemp(),
	})
}

// GetHistory 获取历史记录
func (h *Handler) GetHistory(c *gin.Context) {
	// 实现历史记录查询
}

// HandleGetSmokeDevices 处理获取烟感设备信息请求
func (h *Handler) HandleGetSmokeDevices(c *gin.Context) {
	// 从蓝牙服务获取烟感设备信息
	bluetoothURL := "http://127.0.0.1:8083/api/v1/devices/smoke"

	resp, err := http.Get(bluetoothURL)
	if err != nil {
		logger.SystemError("获取烟感设备信息失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取烟感设备信息失败", "message": err.Error()})
		return
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		bodyBytes, _ := io.ReadAll(resp.Body)
		logger.SystemError("蓝牙服务返回非成功状态码",
			zap.Int("statusCode", resp.StatusCode),
			zap.String("body", string(bodyBytes)))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "蓝牙服务返回错误", "status": resp.StatusCode})
		return
	}

	// 读取原始响应内容用于调试
	bodyBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		logger.SystemError("读取蓝牙服务响应失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "读取蓝牙服务响应失败", "message": err.Error()})
		return
	}

	// 重新创建一个新的Reader，因为原始的Body已经被读取
	resp.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))

	// 读取并解析响应
	var bluetoothResp struct {
		Devices []*bluetooth.ScannedDevice `json:"devices"`
	}

	if err := json.NewDecoder(resp.Body).Decode(&bluetoothResp); err != nil {
		logger.SystemError("解析烟感设备信息失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "解析烟感设备信息失败", "message": err.Error()})
		return
	}

	// 返回设备信息
	c.JSON(http.StatusOK, bluetoothResp)
}

// HandleGetPersonnelDevices 处理获取模拟人员设备信息请求
func (h *Handler) HandleGetPersonnelDevices(c *gin.Context) {
	// 从蓝牙服务获取模拟人员设备信息
	bluetoothURL := "http://127.0.0.1:8083/api/v1/devices/personnel"

	resp, err := http.Get(bluetoothURL)
	if err != nil {
		logger.SystemError("获取模拟人员设备信息失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取模拟人员设备信息失败", "message": err.Error()})
		return
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		bodyBytes, _ := io.ReadAll(resp.Body)
		logger.SystemError("蓝牙服务返回非成功状态码",
			zap.Int("statusCode", resp.StatusCode),
			zap.String("body", string(bodyBytes)))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "蓝牙服务返回错误", "status": resp.StatusCode})
		return
	}

	// 读取原始响应内容用于调试
	bodyBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		logger.SystemError("读取蓝牙服务响应失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "读取蓝牙服务响应失败", "message": err.Error()})
		return
	}

	// 重新创建一个新的Reader，因为原始的Body已经被读取
	resp.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))

	// 读取并解析响应
	var bluetoothResp struct {
		Devices []*bluetooth.ScannedDevice `json:"devices"`
	}

	if err := json.NewDecoder(resp.Body).Decode(&bluetoothResp); err != nil {
		logger.SystemError("解析模拟人员设备信息失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "解析模拟人员设备信息失败", "message": err.Error()})
		return
	}

	// 返回设备信息
	c.JSON(http.StatusOK, bluetoothResp)
}

// 判断是否为监控相关的配置
func (h *Handler) isMonitorConfig(key string) bool {
	// 监控相关的配置前缀
	monitorPrefixes := []string{
		"monitor.",
		"monitor.temp_threshold.",
		"monitor.power_adjust.",
	}

	for _, prefix := range monitorPrefixes {
		if strings.HasPrefix(key, prefix) {
			return true
		}
	}
	return false
}

// 判断是否为MQTT相关的配置
func (h *Handler) isMQTTConfig(key string) bool {
	return strings.HasPrefix(key, "mqtt.")
}

// 判断是否为蓝牙相关的配置
func (h *Handler) isBluetoothConfig(key string) bool {
	return strings.HasPrefix(key, "bluetooth.")
}

// CheckAdminRole 检查是否具有管理员权限
func (h *Handler) CheckAdminRole(c *gin.Context) {
	role, err := c.Cookie("user_role")
	logger.SystemInfo("检查管理员权限",
		zap.String("path", c.Request.URL.Path),
		zap.String("role", role),
		zap.Error(err))

	if err != nil {
		logger.SystemWarn("未找到user_role cookie", zap.Error(err))
		c.JSON(http.StatusForbidden, gin.H{"error": "需要管理员权限", "detail": "未找到用户角色信息"})
		c.Abort()
		return
	}

	if role != "admin" {
		logger.SystemWarn("用户角色不是admin", zap.String("role", role))
		c.JSON(http.StatusForbidden, gin.H{"error": "需要管理员权限", "detail": "用户角色不是管理员"})
		c.Abort()
		return
	}

	logger.SystemInfo("用户具有管理员权限", zap.String("role", role))
	c.Next()
}

// CloseAudioManager 安全关闭音频管理器
func (h *Handler) CloseAudioManager() {
	if h != nil && h.AudioManager != nil {
		h.AudioManager.Close()
	}
}
